在之前的Reactor相關範例中,如果需要測試結果是否符合預期,都必須要透過System.out.println
來印出結果人工檢視,有時候還必須加上Thread.sleep()
來輔助,就算是這樣你都能接受,正式專案通常都有ci/cd來跑測試,這時候總不能還是透過人工去看console,好在Reactor在測試方面也有提供方便的工具給開發者。
提供了聲明式的方式來做驗證,預期的事件或是下一個傳遞的值甚至連時間都可以控制。來看一下官方提供的範例:
首先是一個appendBoomError()
,將傳入的Flux
綁上一個內含Error,覺得這個命名很傳神,就是包裹炸彈一樣。StepVerifier
透過builder的方式,在create
內傳入需要驗證的publisher
,expectNext
就是onNext
,預期下一個data是否符合,也能夠預期錯誤發生,最後verify
就是像subscribe
一樣,當作一個啟動開始測試。
public <T> Flux<T> appendBoomError(Flux<T> source) {
return source.concatWith(Mono.error(new IllegalArgumentException("boom")));
}
@Test
public void testAppendBoomError() {
Flux<String> source = Flux.just("package1", "package2");
StepVerifier.create(
appendBoomError(source))
.expectNext("package1")
.expectNext("package2")
.expectErrorMessage("boom")
.verify();
}
簡單條列一下常用的expect
expectNext
:下一個item與傳入的相同。expectNextMatches(Predicate)
:比較複雜的判斷可以傳入Predicate
assertNext(Consumer)
:直接傳入assertions
expectNextCount(long)
:在下一個訊號之前的item數量expectNextSequence(Iterable)
:一次比對多個item因為error&complete都是終結(terminal)訊號,也就是之後不會再有後續動作,所以可以與verify
結合
verifyComplete()
:publisher結束,傳入已完成的訊號(completion signal)verifyError()
: publisher結束,但是因為有錯誤發生(unspecified error)verifyErrorMessage()
:多加上判斷message//DefaultStepVerifierBuilder.java Source code
@Override
public Duration verifyError() {
return expectError().verify();
}
@Override
public Duration verifyComplete() {
return expectComplete().verify();
}
@Override
public Duration verifyErrorMessage(String errorMessage) {
return expectErrorMessage(errorMessage).verify();
}
最後一個準備一個起始為3總數7個的Flux,透過上面介紹expectNextSequence
一次比對五個item,下一個數字8刻意用Predicate
判斷,expectNextCount
我自己有點難懂,直到實際觀察他的行為才知道比較像是到下一個expect
之前還有的數量,在這邊已經有6個item了,所以只會剩下一個而已,最後就是使用verifyComplete
結合expectComplete
&verify
。
@Test
public void verify(){
Flux<Integer> integers = Flux.range(3,7);
StepVerifier.create(integers)
.expectNextSequence(Arrays.asList(3,4,5,6,7))
.expectNextMatches(d -> (d / 2 ) == 4)
.expectNextCount(1)
.verifyComplete();
}
如果想要更多的練習,有找到一個很棒的resource,reactor 官方github上的hands-on,裡面有非常多Test的範例。